package com.wg.net.client;

import cn.hutool.core.util.StrUtil;
import com.wg.core.lang.IDisposable;
import com.wg.net.NetProtocol;
import com.wg.net.client.core.ClientConfig;
import com.wg.net.client.core.IClient;
import com.wg.net.client.tcp.TcpClient;
import com.wg.net.client.websocket.WebSocketClient;
import com.wg.net.operations.base.OperationRequest;
import com.wg.net.operations.base.OperationResponse;

import java.net.URI;
import java.net.URISyntaxException;

/**
 * 统一客户端入口类（根据协议类型创建具体客户端实例）
 *
 * @author 少爷123
 */
public abstract class WgClient implements IDisposable {
    /**
     * 超时(毫秒)
     */
    private final int timeout;

    /**
     * ping(毫秒)
     */
    private final int pingInterval;

    /**
     * 断开超时(毫秒)
     */
    private final int disconnectTimeout;

    /**
     * 客户端
     */
    private IClient client;

    public WgClient(int timeout, int pingInterval, int disconnectTimeout) {
        this.timeout = Math.max(timeout, 0);
        this.pingInterval = Math.max(pingInterval, 0);
        this.disconnectTimeout = Math.max(disconnectTimeout, 0);
    }

    public void connect(String url, String appId) throws Exception {
        URI uri;
        try {
            uri = new URI(url);
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException("Invalid URL format: " + url, e);
        }

        if (StrUtil.isBlank(appId)) {
            throw new IllegalArgumentException("AppId cannot be null or empty");
        }

        if (client != null) {
            client.dispose();
            client = null;
        }

        ClientConfig config = new ClientConfig(uri, appId);
        NetProtocol netProtocol = NetProtocol.valueOfByPrefix(uri.getScheme());
        switch (netProtocol) {
            case TCP:
                client = new TcpClient(this, config);
                break;
            case WEBSOCKET:
            case WEBSOCKETS:
                client = new WebSocketClient(this, config);
                break;
            default:
                throw new IllegalArgumentException("Unsupported protocol: " + netProtocol.getPrefix());
        }
        client.connect();
    }

    @Override
    public void dispose() {
        if (client != null) {
            client.dispose();
        }
    }

    public void close() {
        if (!isConnected()) {
            return;
        }

        client.close();
    }

    public void sendOperationRequest(OperationRequest request) {
        if (!isConnected()) {
            return;
        }
        client.sendOperationRequest(request);
    }

    public int getPingInterval() {
        return pingInterval;
    }

    public int getTimeout() {
        return timeout;
    }

    public boolean isConnected() {
        return client != null && client.isConnected();
    }

    public int getDisconnectTimeout() {
        return disconnectTimeout;
    }

    /**
     * 连接成功
     */
    public abstract void onConnected();

    /**
     * 连接失败
     */
    public abstract void onConnectionFail();

    /**
     * 断开
     */
    public abstract void onDisconnect();

    /**
     * 操作响应
     *
     * @param response 响应
     */
    public abstract void onOperationResponse(OperationResponse response);
}
